package nsl.com.util.excel.basic;


import nsl.com.util.excel.bean.ExcelPoint;

import java.util.HashMap;
import java.util.Map;

/**
 * Description: coordinate cell address,convert  A1 to (0,0), or reserve.
 * Created by 4790K_NSL on 2017/4/29.
 */
public class UtilExcelCoordinateConverter {
    //{<A:0>,<B:1>....>
    static private Map<String,Integer> letterMap=new HashMap<>();
    static {
        for (int i = 65; i <91 ; i++) {
            char letter= (char) i;
           // System.out.println(letter);
            letterMap.put(letter+"",i-65);
        }
        //System.out.println(letterMap);
    }

    public static void main(String[] args) {


    }

    /**
     * 根据基准点和偏移量，得到偏移后的点位置
     * @param origin
     * @param offset
     * @return
     */
    static public ExcelPoint getDestinationAfterOffset(ExcelPoint origin, ExcelPoint offset){
        int x=origin.getX()-offset.getX();
        int y=origin.getY()-offset.getY();
        if(x<0 || y<0){
            throw new RuntimeException("offset point error.");
        }
        return new ExcelPoint(x,y);
    }


    /**
     * Convert A1 -> (0,0)
     * @param cellAddress like 'B2'
     * @return ExcelPoint
     */
    static public  ExcelPoint convertCellAddressFromString2Point(String cellAddress){
        ExcelPoint point=new ExcelPoint(-1,-1);
        if(cellAddress==null || cellAddress.trim().equals("")){
            throw new RuntimeException("cellAddres in null.");
        }

        cellAddress=cellAddress.toUpperCase();
        if(!cellAddress.matches("[A-Z]+[1-9]+[0-9]*")){
            throw new RuntimeException("cellAddress in illegal.");
        }
        String columnString=cellAddress.replaceAll("\\d+","");
        String rowString=cellAddress.replaceAll("\\D+","");
        //System.out.println(columnString);
        //System.out.println(rowString);
        int x= convertColumnAddressFromLetter2Index(columnString);
        int y=Integer.parseInt(rowString)-1;
        point.setLocation(x,y);
        return  point;
    }

    /**
     * 使用递归的方式，转换列坐标： A->0 , AB->27
     * @param columnString
     * @param lastRound
     * @return
     */
    static private int convertColumnAddressFromLetter2Index(String columnString, int lastRound){
        if(columnString.length()>1){
           String highLetter=columnString.charAt(0)+"" ;
           String rightLetters=columnString.substring(1);
           int high=(letterMap.get(highLetter)+1)+lastRound*26;
            //System.out.println(rightLetters);
            //System.out.println(high);
            return convertColumnAddressFromLetter2Index(rightLetters,high);

        }else {
            return letterMap.get(columnString)+lastRound*26;
        }
    }


    /**
     * 将字母形式的列名,转换成整数返回.
     * 起点为0. A=0;AA=26;
     * @param columnString  列坐标: A or AB
     * @return
     */
    static public int convertColumnAddressFromLetter2Index(String columnString){
        if (columnString==null || columnString.trim().equals("")) {
            throw new RuntimeException(columnString+" is null or empty.");
        }
        columnString=columnString.toUpperCase();
        return  convertColumnAddressFromLetter2Index(columnString,0);
    }

    /**
     * 将整数形式的列坐标名,转换成字母形式,并返回.
     * 起点为0. 0=A;26=AA;
     * @param i 0;1;2....
     * @return A,B....
     */
    // 27->AB,i 最小为0
    public static String convertColumnAddressFromIndex2Letter(int i){
        if(i<0){
            throw new RuntimeException("i<0 is wrong.");
        }
        String columnName="";
        if(i<26){
            return  getSimpleLetter(i);
        }else{
            int mod=i%26;
            String rearLetter=getSimpleLetter(mod);
            columnName= convertColumnAddressFromIndex2Letter(i/26-1)+rearLetter;
        }
        return columnName;
    }

    /**
     * 根据列序号,返回列字母标号,从0开始.
     * 0=A;1=B....
     * @param i i必须小于26
     * @return
     */
    //
    private static String getSimpleLetter(int i){
        if(i>=26){
            throw new RuntimeException("i 值 不能大于等于26.");
        }
        char letter = (char)(i+65);
        return  letter+"";
    }

}
